/*
 * 显示驱动程序 - 书籍显示驱动
 * 
 * 主要功能：
 * - 为Book对象实现显示形状的生成逻辑
 * - 定义书籍不同部分的显示位置和方式
 * - 支持可重用的显示形状
 * - 提供灵活的显示布局控制
 */

using Lombiq.TrainingDemo.Models;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.DisplayManagement.Views;
using System.Diagnostics.CodeAnalysis;

namespace Lombiq.TrainingDemo.Drivers;

/// <summary>
/// 书籍显示驱动程序 - 为Book对象实现显示形状生成
/// 
/// 主要用途：
/// - 为Book对象实现显示形状的生成逻辑
 /* - 定义书籍不同部分的显示位置和方式
 * - 支持可重用的显示形状
 * - 提供灵活的显示布局控制
 * 
 * 使用场景：
 * - 显示书籍标题、作者、封面和描述
 * - 在不同区域（Header、Cover、Content）显示不同内容
 * - 根据显示类型（Description）控制内容显示
 * - 提供可重用的显示组件
 * 
 * 设计原因：
 * - 分离显示逻辑与数据模型
 * - 提供灵活的显示布局控制
 * - 支持显示形状的重用和覆盖
 * - 实现模块化的显示组件
 * 
 * 设计模式：
 * - 驱动模式：继承DisplayDriver实现显示逻辑
 * - 组合模式：使用Combine方法组合多个形状
 * - 位置模式：使用Location定义显示位置
 * - 视图模式：使用View方法生成显示形状
/// </summary>
// DisplayDrivers用于实现DisplayManager生成的特定形状的功能。您可以为任何对象（持久化或非持久化）创建驱动程序，
// 在其中实现生成可重用形状的特定逻辑。在编辑器形状的情况下，模型更新和自定义验证也在这些驱动程序中完成。
// 最后，您可以为一个对象创建多个驱动程序，DisplayManager将确保使用所有驱动程序并执行其特定逻辑。
// 不要忘记在服务提供程序中注册此类（请参阅：Startup.cs）。
 */
public sealed class BookDisplayDriver : DisplayDriver<Book>
{
    /// <summary>
    /// 显示方法 - 为Book对象生成显示形状
    /// 
    /// 功能说明：
    /// - 为Book对象注册显示形状
    /// - 定义不同部分的显示位置
    /// - 支持显示类型控制
    /// - 使用Combine方法组合多个形状
    /// 
    /// 显示区域：
    /// - Header: 1 - 标题显示位置
    /// - Header: 2 - 作者显示位置
    /// - Cover: 1 - 封面显示位置
    /// - Content: 1 - 描述显示位置（仅在Description显示类型时显示）
    /// 
    /// 显示类型：
    /// - 无显示类型：标题、作者、封面始终显示
    /// - Description：描述仅在Description显示类型时显示
    /// </summary>
    /// <param name="model">要显示的Book模型</param>
    /// <param name="context">显示构建上下文</param>
    /// <returns>组合的显示结果</returns>
    [SuppressMessage(
        "StyleCop.CSharp.ReadabilityRules",
        "SA1114:Parameter list should follow declaration",
        Justification = "Necessary for comments.")]
    public override IDisplayResult Display(Book model, BuildDisplayContext context) =>
        // 为了演示，我们在这里使用Combined()。它使得可以从驱动程序方法返回多个形状
        // - 不一定同时显示所有形状！
        Combine(
            // 这里我们为标题定义一个形状。不必将这些分割成原子片段，但为标题制作可重用形状是有意义的，
            // 这也使得仅覆盖这些片段成为可能（比如您将此模块交给某人，他们想在自己的站点上以不同方式显示标题，
            // 而无需修改您的模块）。有多种帮助器可用于渲染形状（显示或编辑），当您不想为视图模型烦恼时，
            // 这个View()很方便（在这种情况下，视图模型将是ShapeViewModel<Book>，您会看到的）。
            // 在Location帮助器中，您为形状定义一个位置。"Header"意味着它将在Header区域显示。"1"意味着它将是Header区域中的第一个。
            // 很快您就会看到这些区域是什么。
            View($"{nameof(Book)}_Display_Title", model)
                .Location("Header: 1"),
            // 这里同样适用。这个形状也将在Header区域显示，但在第二个位置。
            View($"{nameof(Book)}_Display_Author", model)
                .Location("Header: 2"),
            // 为封面照片创建一个单独的形状。这将进入不同的区域，"Cover"区域。
            View($"{nameof(Book)}_Display_Cover", model)
                .Location("Cover: 1"),
            // 描述的形状将是Content区域中的第一个。但是，您可以看到这里的另一个参数，即显示类型。
            // 它用于区分显示形状的情况。假设您想始终显示标题、作者和封面（无形状类型参数），
            // 但描述仅在显示类型为"Description"时显示。您将看到一个示例。
            // 虽然我们可以选择任何显示类型，但传统的类型是"Detail"、"Summary"和"SummaryAdmin"，
            // 它们用于ContentItem相关的形状。
            View($"{nameof(Book)}_Display_Description", model)
                .Location("Description", "Content: 1"));

    // 现在让我们看看这些区域是什么，并慢慢澄清您在上面看到的所有这些东西！
    // 下一站：Views/Book.cshtml。
}
